/*
 * SymTp.java
 *
 * Created on 19 marzo 2004, 14.56
 */

package net.ermannofranco.xml.schema;

import net.ermannofranco.xml.Static;

/**
 * Classe che formalizza un tipo semplice.
 * 
 * @author ermanno (ermanno.franco@gmail.com)
 */
public class SimpleType extends SchemaTag implements ContentType {
	/**
	 * 
	 */
	private static final long serialVersionUID = -4358027816071555095L;
	private String nome;
	private boolean assigned;
	private BaseTypeContainer child;

	/**
	 * Creates a new instance of SimpleType Protetto
	 * 
	 * @param level
	 *            livello di indentazione
	 * @param container
	 *            tag contenitore
	 */
	protected SimpleType(int level, ISchemaTag container) {
		super("simpleType", level, container);
	}

	/**
	 * assegna il nome del tipo
	 * 
	 * @param name
	 *            nome del tipo
	 * @return autoref
	 */
	protected SimpleType setName(String name) {
		if (level > 1)
			throw new SchemaException("Name not allowed in inner level");
		Static.validateNMToken(name);
		this.nome = name;
		addAttr("name", nome);
		return this;
	}

	public RestrictionSimpleType setRestriction() {
		RestrictionSimpleType re;
		if (assigned)
			throw new SchemaException(
					"Restriction non permessa, contenuto gia' assegnato, "
							+ getClass().getName() + ":(" + getName() + ")");
		add(re = new RestrictionSimpleType(getLevel() + 1, this));
		assigned = true;
		child = re;
		return re;
	}

	/**
	 * assegna una restrizione, specificando il tipo di base della restrizione.
	 * 
	 * @return riferimento all'oggetto Restriction
	 */
	public RestrictionSimpleType setRestriction(XmlType type) {
		RestrictionSimpleType re = setRestriction();
		re.setBase(type);
		return re;
	}

	public RestrictionSimpleType setRestriction(SimpleType type) {
		RestrictionSimpleType re = setRestriction();
		re.setBase(type);
		return re;
	}

	/**
	 * assegna una restrizione al tipo; metodo che semplifica l'operazione in
	 * caso di restrizione semplice
	 * 
	 * @param simpleTypeNumber
	 *            tipo interessato dalla restrizione
	 * @param facetType
	 *            indicatore di restrizione. Usare costante della classe Facet
	 * @param value
	 *            valore della restrizione
	 * @return autoref, a SimpleType, NON a Restriction
	 */
	public SimpleType setRestriction(XmlType simpleTypeNumber, Facet facetType,
			String value) {
		RestrictionSimpleType re;
		if (assigned)
			throw new SchemaException(
					"Restriction non permesso, contenuto gia' assegnato, "
							+ getClass().getName() + ":(" + getName() + ")");
		add(re = new RestrictionSimpleType(getLevel() + 1, this));
		re.setBase(simpleTypeNumber).addFacet(facetType, value);
		assigned = true;
		child = re;
		return this;
	}

	/**
	 * assegna un tag list al tipo
	 * 
	 * @return oggetto List
	 */
	public List setList() {
		List li;
		if (assigned)
			throw new SchemaException(
					"List non permesso, contenuto gia' assegnato, "
							+ getClass().getName() + ":(" + getName() + ")");
		add(li = new List(getLevel() + 1, this));
		assigned = true;
		child = li;
		return li;
	}

	/**
	 * assegna un tag list al tipo
	 * 
	 * @return oggetto Union
	 */
	public Union setUnion() {
		Union li;
		if (assigned)
			throw new SchemaException(
					"Union non permesso, contenuto gia' assegnato, "
							+ getClass().getName() + ":(" + getTypeName() + ")");
		add(li = new Union(getLevel() + 1, this));
		assigned = true;
		child = li;
		return li;
	}

	/**
	 * aggiunge un tag Annotation che contiene un tag Documentation
	 * 
	 * @param explanation
	 *            Stringa di documentazione
	 * @return autoriferimento all'oggetto corrente
	 */
	public SimpleType addDocumentation(String explanation) {
		addAnnotation().addDocumentation(explanation);
		return this;
	}

	/**
	 * aggiunge un tag Annotation che contiene un tag Documentation
	 * 
	 * @param explanation
	 *            testo della documentazione
	 * @param language
	 *            attributo di xml:lang, seguire le regole di i18n
	 * @return riferimento all'oggetto corrente
	 */
	public SimpleType addDocumentation(String explanation, String language) {
		addAnnotation().addDocumentation(explanation, language);
		return this;
	}

	private void validateST() {
		if (!assigned)
			throw new SchemaException("contenuto obbligatorio, "
					+ getClass().getName() + ":(" + getName() + ")");
	}

	/**
	 * semplice override di convalida
	 * 
	 * @return super.toString()
	 */
	public String toPrint() {
		validateST();
		return super.toPrint();
	}

	public String toSave() {
		validateST();
		return super.toSave();
	}

	/**
	 * Fornisce il nome del tipo, per uso in setRef():
	 */
	public String getTypeName() {
		String ret = getAttribute("name");
		return ret == null ? "<simpleType_without_name>" : ret;
	}

	public boolean isNotVeryComplex() {
		return true;
	}

	public java.util.List<XmlType> getBaseTypes() {
		java.util.List<XmlType> baseTypes = child.getBaseTypes();
		log.debug("baseTypes for " + getTypeName() + ": " + baseTypes);
		return baseTypes;
	}
}
